home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / _divdf3.cpp < prev    next >
C/C++ Source or Header  |  1992-03-30  |  5KB  |  252 lines

  1. #if !defined (__M68881__) && !defined (sfp004)
  2.  
  3. | double floating point divide routine
  4. |
  5. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  6. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  7. |
  8. |
  9. | Revision 1.2, kub 01-90 :
  10. | added support for denormalized numbers
  11. |
  12. | Revision 1.1, kub 12-89 :
  13. | Ported over to 68k assembler
  14. |
  15. | Revision 1.0:
  16. | original 8088 code from P.S.Housel
  17.  
  18. BIAS8    =    0x3FF-1
  19.  
  20.     .text
  21.     .even
  22.     .globl    __divdf3, ___divdf3
  23.     .globl    __infinitydf
  24.  
  25. # ifdef    ERROR_CHECK
  26. LC0:
  27.     .ascii "floating point division by 0\12\15\0"
  28.     .even
  29. # endif    ERROR_CHECK
  30.  
  31. __divdf3:
  32. ___divdf3:
  33.  
  34. # ifdef    ERROR_CHECK
  35.     tstl    a7@(12)            | check if divisor is 0
  36.     bne    continue
  37.     tstl    a7@(16)
  38.     bne    continue
  39.  
  40.     moveml    d0-d1,a7@-
  41.     pea    LC0
  42.     pea    __iob+52    |
  43.     jbsr    _fprintf    |
  44.     addql    #8,a7        |
  45.     moveml    a7@+,d0-d1
  46.                     | set _errno to ERANGE
  47. #  ifdef __MSHORT__
  48.     movew    #63,_errno
  49. #  else
  50.     movel    #63,_errno
  51. #  endif
  52.     movel    #0x7ff00000,d0        | return signed infinity 
  53.     clrl    d1            |
  54.     btst    #31,a7@(4)        | transfer sign of dividend
  55.     beq    clear            | (mjr++)
  56.     bset    #31,d0            |
  57.     rts                |
  58. clear:                    |
  59.     bclr    #31,d0            |
  60.     rts
  61. continue:
  62.  
  63. # endif    ERROR_CHECK
  64.  
  65.     lea    sp@(4),a0    | pointer to parameters u and v
  66.     moveml    d2-d7,sp@-    | save registers
  67.     moveml    a0@,d4-d5/d6-d7    | d4-d5 = u, d6-d7 = v
  68.  
  69.     movel    d4,d0        | d0 = u.exp
  70.     swap    d0
  71.     movew    d0,d2        | d2 = u.sign
  72.     lsrw    #4,d0
  73.     andw    #0x07ff,d0    | kill sign bit
  74.  
  75.     movel    d6,d1        | d1 = v.exp
  76.     swap    d1
  77.     eorw    d1,d2        | d2 = u.sign ^ v.sign (in bit 31)
  78.     lsrw    #4,d1
  79.     andw    #0x07ff,d1    | kill sign bit
  80.  
  81.     andl    #0x0fffff,d4    | remove exponent from u.mantissa
  82.     tstw    d0        | check for zero exponent - no leading "1"
  83.     beq    0f
  84.     orl    #0x100000,d4    | restore implied leading "1"
  85.     bra    1f
  86. 0:    addw    #1,d0        | "normalize" exponent
  87. 1:    movel    d4,d3
  88.     orl    d5,d3
  89.     beq    retz        | dividing zero
  90.  
  91.     andl    #0x0fffff,d6    | remove exponent from v.mantissa
  92.     tstw    d1        | check for zero exponent - no leading "1"
  93.     beq    0f
  94.     orl    #0x100000,d6    | restore implied leading "1"
  95.     bra    1f
  96. 0:    addw    #1,d1        | "normalize" exponent
  97. 1:    movel    d6,d3
  98.     orl    d7,d3
  99.  
  100. #ifndef    ERROR_CHECK
  101.     beq    divz        | divide by zero
  102. #endif    ERROR_CHECK
  103.  
  104.     movew    d2,a0        | save sign
  105.  
  106.     subw    d1,d0        | subtract exponents,
  107.     addw    #BIAS8-11+1,d0    |  add bias back in, account for shift
  108.     addw    #66,d0        |  add loop offset, +2 for extra rounding bits
  109.                 |   for denormalized numbers (2 implied by dbra)
  110.     movew    #24,d1        | bit number for "implied" pos (+4 for rounding)
  111.     movel    #-1,d2        | zero the quotient
  112.     movel    #-1,d3        |  (for speed it is a one''s complement)
  113.     subl    d7,d5        | initial subtraction,
  114.     subxl    d6,d4        | u = u - v
  115. 2:
  116.     btst    d1,d2        | divide until 1 in implied position
  117.     beq    5f
  118.  
  119.     addl    d5,d5
  120.     addxl    d4,d4
  121.     bcs    4f        | if carry is set, add, else subtract
  122.  
  123.     addxl    d3,d3        | shift quotient and set bit zero
  124.     addxl    d2,d2
  125.     subl    d7,d5        | subtract
  126.     subxl    d6,d4        | u = u - v
  127.     dbra    d0,2b        | give up if result is denormalized
  128.     bra    5f
  129. 4:
  130.     addxl    d3,d3        | shift quotient and clear bit zero
  131.     addxl    d2,d2
  132.     addl    d7,d5        | add (restore)
  133.     addxl    d6,d4        | u = u + v
  134.     dbra    d0,2b        | give up if result is denormalized
  135. 5:    subw    #2,d0        | remove rounding offset for denormalized nums
  136.     notl    d2        | invert quotient to get it right
  137.     notl    d3
  138.  
  139.     movel    d2,d4        | save quotient mantissa
  140.     movel    d3,d5
  141.     movew    a0,d2        | get sign back
  142.     clrw    d1        | zero rounding bits
  143.     jmp    norm_df        | (registers on stack removed by norm_df)
  144.  
  145. retz:    clrl    d0        | zero destination
  146.     clrl    d1
  147.     moveml    sp@+,d2-d7
  148.     rts            | no normalization needed
  149.  
  150. #ifndef    ERROR_CHECK
  151. divz:    moveml    __infinitydf,d0-d1 | return infinty value
  152.     moveml    sp@+,d2-d7    | should really cause trap ?!?
  153.  
  154.     btst    #31,a7@(4)        | transfer sign of dividend
  155.     beq    clear            | (mjr++)
  156.     bset    #31,d0            |
  157.     rts                |
  158. clear:                    |
  159.     bclr    #31,d0            |
  160.     rts
  161.  
  162. #endif    ERROR_CHECK
  163.  
  164. #endif
  165. #ifdef    sfp004
  166.  
  167. | double precision floating point stuff for Atari-gcc using the SFP004
  168. | developed with gas
  169. |
  170. | double precision division
  171. |
  172. | M. Ritzert (mjr at dmzrzu71)
  173. |
  174. | 4.10.1990
  175. |
  176. | no NAN checking implemented to gain compatibility with the TT-lib
  177. |
  178. | addresses of the 68881 data port. This choice is fastest when much data is
  179. | transferred between the two processors.
  180.  
  181. comm =     -6
  182. resp =    -16
  183. zahl =      0
  184.  
  185. | waiting loop ...
  186. |
  187. | wait:
  188. | ww:    cmpiw    #0x8900,a0@(resp)
  189. |     beq    ww
  190. | is coded directly by
  191. |    .long    0x0c688900, 0xfff067f8
  192.  
  193. # ifdef    ERROR_CHECK
  194. LC0:
  195.     .ascii "floating point division by 0\12\15\0"
  196.     .even
  197. # endif    ERROR_CHECK
  198.  
  199.     .text
  200.     .even
  201.     .globl    __divdf3, ___divdf3
  202.  
  203. __divdf3:
  204. ___divdf3:
  205.  
  206. # ifdef    ERROR_CHECK
  207.     tstl    a7@(12)            | check if divisor is 0
  208.     bne    continue
  209.     tstl    a7@(16)
  210.     bne    continue
  211.  
  212.     moveml    d0-d7/a0-a6,a7@-    | print error message
  213.     pea    LC0
  214.     movew    #9,a7@-
  215.     trap    #1
  216.     addql    #6,a7
  217.     moveml    a7@+,d0-d7/a0-a6
  218.                     | set _errno to ERANGE
  219. #  ifdef __MSHORT__
  220.     movew    #63,_errno
  221. #  else
  222.     movel    #63,_errno
  223. #  endif
  224.     movel    #0x7ff00000,d0        | return signed infinity 
  225.     clrl    d1            |
  226.     btst    #31,a7@(4)        | transfer sign of dividend
  227.     beq    clear            | (mjr++)
  228.     bset    #31,d0            |
  229.     rts                |
  230. clear:                    |
  231.     bclr    #31,d0            |
  232.     rts
  233. continue:
  234.  
  235. # endif    ERROR_CHECK
  236.  
  237.     lea    0xfffa50,a0
  238.     movew    #0x5400,a0@(comm)    | load first argument to fp0
  239.     cmpiw    #0x8900,a0@(resp)    | check
  240.     movel    a7@(4),a0@
  241.     movel    a7@(8),a0@
  242.     movew    #0x5420,a0@(comm)
  243.     .long    0x0c688900, 0xfff067f8
  244.     movel    a7@(12),a0@
  245.     movel    a7@(16),a0@
  246.     movew    #0x7400,a0@(comm)    | result to d0
  247.     .long    0x0c688900, 0xfff067f8
  248.     movel    a0@,d0
  249.     movel    a0@,d1
  250.      rts
  251. #endif    sfp004
  252.